// EngineFactory.cpp
//
//////////////////////////////////////////////////////////////////////

#include "EngineFactory.h"
#ifndef WIN32
#include <dlfcn.h>
void  * FunctionLib=NULL;
#endif
EngineFactory::EngineFactory(){

}

EngineFactory::~EngineFactory(){
#ifndef WIN32
        if(FunctionLib)
                dlclose(FunctionLib);
#endif
        engineMap.clear();
}

typedef Engine3D * __cdecl (*MYPROC)();
typedef void __cdecl (*MYPROC2)(char *);
void EngineFactory::scanEngines(){
#ifdef WIN32
    HINSTANCE hinstLib; 
    MYPROC2 ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
        char store[100];
        WIN32_FIND_DATA findFileData ;
        HANDLE f=::FindFirstFile("*.dll", &findFileData);
        BOOL notFinished=TRUE;
 
        while((f!=INVALID_HANDLE_VALUE)&&(notFinished)){
                hinstLib = ::LoadLibrary(findFileData.cFileName); 
 
                if (hinstLib != NULL) {
                        ProcAdd = (MYPROC2) GetProcAddress(hinstLib, "getEngineNameString");
                        if (fRunTimeLinkSuccess = (ProcAdd != NULL)){
                                (ProcAdd) (store); 
                                engineMap.push_back(STRINGMAP::value_type(store,findFileData.cFileName));
                        }
                         fFreeResult = FreeLibrary(hinstLib); 
                } 
                notFinished=::FindNextFile(f, &findFileData);
        }
#else
        /*TODO: scan the folder*/  
        engineMap.push_back(STRINGMAP::value_type("Prueba","engine.dll"));      
#endif
}

Engine3D * EngineFactory::create(unsigned index){
#ifdef WIN32
        HINSTANCE hinstLib; 
    MYPROC ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
        
    hinstLib = ::LoadLibrary(engineMap[index].second.c_str()); 
    if (hinstLib != NULL) 
    { 
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, "getEngine"); 
        if (fRunTimeLinkSuccess = (ProcAdd != NULL)) 
            return (Engine3D *)(ProcAdd) (); 
 //        fFreeResult = FreeLibrary(hinstLib); 
    } 
 
    return NULL;
#else
        /*Todo: open the real one*/
        MYPROC func=NULL;
        FunctionLib=dlopen("./engine.so.1.0.1",RTLD_LAZY);
        func=(MYPROC)dlsym( FunctionLib, "getEngine");
        const char * eror=dlerror();
        return func();
#endif
}

unsigned EngineFactory::getEnginesNumber(){
        return engineMap.size();
}

std::string EngineFactory::getEngineName(unsigned index){
        return engineMap[index].first;  
}
